{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* $Fashion-MNIST$是一个服装分类数据集，由10个类别的图像组成。\n",
    "* 我们将高度为$h$像素宽度为$w$像素的图像记为$h \\times w$或$(h,w)$。\n",
    "* 数据迭代器是获得更高性能的关键组件，依靠实现良好的数据迭代器，利用高性能计算来避免减慢训练过程。\n",
    "  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "os.environ[\"KMP_DUPLICATE_LIB_OK\"] = \"TRUE\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "from d2l import torch as d2l\n",
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "from torch.utils import data\n",
    "\n",
    "d2l.use_svg_display()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 读取数据集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 通过ToTensor实例将图像数据从PIL类型变换成32位浮点数格式，\n",
    "# 并除以255使得所有像素的数值均在0～1之间\n",
    "trans = transforms.ToTensor()\n",
    "mnist_train = torchvision.datasets.FashionMNIST(root='../data', train=True, download=True, transform=trans)\n",
    "mnist_test = torchvision.datasets.FashionMNIST(root='../data', train=False, download=True, transform=trans)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(60000, 10000)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(mnist_train),len(mnist_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 28, 28])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mnist_train[0][0].shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# @save\n",
    "def get_fashion_mnist_labels(labels):\n",
    "    text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',\n",
    "                   'sandal','shirt','sneaker', 'bag', 'ankle boot']\n",
    "    return [text_labels[int(i)] for i in labels]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# @save\n",
    "def show_images(img,num_rows,num_cols,titles = None,scale = 1.5):\n",
    "    \"\"\"绘制图像列表\"\"\"\n",
    "    figsize = (num_cols*scale,num_rows*scale)\n",
    "    _,axes = d2l.plt.subplots(num_rows,num_cols,figsize = figsize)\n",
    "    axes = axes.flatten()\n",
    "    for  i ,(ax,img) in enumerate(zip(axes,img)):\n",
    "        if torch.is_tensor(img):\n",
    "            # 图片张量\n",
    "            ax.imshow(img.numpy())\n",
    "        else:\n",
    "            # PIL图片\n",
    "            ax.imshow(img)\n",
    "        ax.axes.get_xaxis().set_visible(False)\n",
    "        ax.axes.get_yaxis().set_visible(False)\n",
    "        if titles:\n",
    "            ax.set_title(titles[i])\n",
    "    return axes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([<Axes: title={'center': 'ankle boot'}>,\n",
       "       <Axes: title={'center': 't-shirt'}>,\n",
       "       <Axes: title={'center': 't-shirt'}>,\n",
       "       <Axes: title={'center': 'dress'}>,\n",
       "       <Axes: title={'center': 't-shirt'}>,\n",
       "       <Axes: title={'center': 'pullover'}>,\n",
       "       <Axes: title={'center': 'sneaker'}>,\n",
       "       <Axes: title={'center': 'pullover'}>,\n",
       "       <Axes: title={'center': 'sandal'}>,\n",
       "       <Axes: title={'center': 'sandal'}>,\n",
       "       <Axes: title={'center': 't-shirt'}>,\n",
       "       <Axes: title={'center': 'ankle boot'}>,\n",
       "       <Axes: title={'center': 'sandal'}>,\n",
       "       <Axes: title={'center': 'sandal'}>,\n",
       "       <Axes: title={'center': 'sneaker'}>,\n",
       "       <Axes: title={'center': 'ankle boot'}>,\n",
       "       <Axes: title={'center': 'trouser'}>,\n",
       "       <Axes: title={'center': 't-shirt'}>], dtype=object)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X, y = next(iter(data.DataLoader(mnist_train, batch_size = 18)))\n",
    "show_images(X.reshape(18, 28, 28), 2, 9,titles = get_fashion_mnist_labels(y))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.5.2 读取小批量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "batch_size = 256\n",
    "\n",
    "#@save\n",
    "def get_dataloader_workers():  \n",
    "    \"\"\"使用4个进程来读取数据\"\"\"\n",
    "    return 4\n",
    "\n",
    "train_iter = data.DataLoader(mnist_train, batch_size, shuffle = True, num_workers = get_dataloader_workers())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'6.89 sec'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "timer = d2l.Timer()\n",
    "for X,y in train_iter:\n",
    "    continue\n",
    "f'{timer.stop():.2f} sec'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3.5.3 整合所有组件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# @save\n",
    "def load_data_fashion_mnist(batch_size, resize=None):\n",
    "    \"\"\"下载Fashion-MNIST数据集,然后将其加载到内存中\"\"\"\n",
    "    trans = [transforms.ToTensor()]\n",
    "    if resize:\n",
    "        trans.insert(0, transforms.Resize(resize))\n",
    "    trans = transforms.Compose(trans)\n",
    "    mnist_train = torchvision.datasets.FashionMNIST(root = '../data', train = True, transform = trans, download = True)\n",
    "    mnist_test = torchvision.datasets.FashionMNIST(root = '../data', train = False, transform = trans, download = True)\n",
    "    return (data.DataLoader(mnist_train, batch_size, shuffle = True, num_workers = get_dataloader_workers()),\n",
    "            data.DataLoader(mnist_test, batch_size, shuffle = False, num_workers = get_dataloader_workers()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([32, 1, 64, 64]) torch.float32 torch.Size([32]) torch.int64\n"
     ]
    }
   ],
   "source": [
    "train_iter, test_iter = load_data_fashion_mnist(32, resize = 64)\n",
    "for X, y in train_iter:\n",
    "    print(X.shape,X.dtype,y.shape,y.dtype)\n",
    "    break"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
